using System;
using System.IO;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
using System.Threading;
using System.Net;
using System.Net.Sockets;
using Microsoft.BizTalk.Message.Interop;
using Microsoft.BizTalk.TransportProxy.Interop;

namespace Microsoft.Samples.BizTalk.Adapter.Tcp
{
    /// <summary>
    ///     This class represents a batch containing a set of batch messages and a set of helper
    ///     functions to submit messages to batches.
    /// </summary>
    /// <author>
    ///     Paul Brown
    /// </author>
    public sealed partial class Batch : IBTBatchCallBack, IDisposable
    {
        #region IBTBatchCallBack Members

        /// <summary>
        ///     The messaging engine calls this callback function once a batch has been completed.
        /// </summary>
        public void BatchComplete(int status, short opCount, BTBatchOperationStatus[] operationStatus, object callbackCookie)
        {
            // Did batch fail?
            if (status < 0)
            {
                // Failed
                TraceHelper.WriteEntry(TraceLevel.Error, ResourceConstants.BizTalkBatchCompleteFailed, callbackCookie, status);

                try
                {
                    // Manage failure of batch
                    this.HandleBatchFailure(opCount, operationStatus);
                }
                catch (Exception e)
                {
                    TraceHelper.WriteEntry(TraceLevel.Error, ResourceConstants.BizTalkBatchFailedHandlingBatchFailure, callbackCookie, e.Message);

                    // Save data off to disk here to preserve it
                    this.Save();

                    // Set flag to indicate batch failed processing
                    this.BatchFailed = true;

                    // Remove batch from type collection if this is the top level as we are finished with it
                    if (this.TopLevelBatch == null)
                    {
                        Batch.RemoveBatch(this.BatchCookie);
                    }
                }

                // Release SubmitBatch() call if ordered
                if (this.OrderedBatch)
                {
                    // The handle batch failure will block until complete, when complete it releases submit that caused
                    // this BatchComplete to be invoked.
                    this.OrderedEvent.Set();
                }
            }
            else
            {
                // Success
                if (this.Adapter.TraceSwitch.TraceVerbose)
                    TraceHelper.WriteEntry(TraceLevel.Verbose, ResourceConstants.BizTalkBatchSubmissionSuccess, callbackCookie);

                // Release SubmitBatch() call if ordered
                if (this.OrderedBatch)
                {
                    // The handle batch failure will block until complete, when complete it releases submit that caused
                    // this BatchComplete to be invoked.
                    this.OrderedEvent.Set();
                }

                // Remove batch
                if (this.TopLevelBatch == null)
                {
                    // Remove main batch
                    Batch.RemoveBatch(this.BatchCookie);
                }
                else
                {
                    // Remove failure batch
                    this.TopLevelBatch.RemoveFailureBatch(this.BatchCookie);
                }
            }
        }

        #endregion
    }
}
